package org.scnu.nidd;

import java.awt.BasicStroke;
import java.awt.Color;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import java.util.TreeMap;
import java.util.Map.Entry;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartFrame;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.DefaultXYDataset;
import org.scnu.model.Kneigh;
import org.scnu.util.DataTypeConversion;
import org.scnu.util.ReadFileTxt;



public class NIDD {


	public static void Main(Double mju,Double intersect_rate, Double epsilon,String filename,int k ) throws FileNotFoundException{

		List<Kneigh> all_k_neigh = new ArrayList<>();
		List<Kneigh> all_k_neigh_sorted = new ArrayList<>(all_k_neigh.size());	
		List<String[]> points = ReadFileTxt.readFileByLines(filename);
		double[][] distanceMatrix = getDistanceMatrix(points);
		all_k_neigh = findTopKNeighbors(points, distanceMatrix, k);
		// 深度克隆
		Iterator<Kneigh> iterator = all_k_neigh.iterator();
		while (iterator.hasNext()) {
			all_k_neigh_sorted.add(iterator.next().clone());
		}
		all_k_neigh_sorted = sortKneight(all_k_neigh_sorted);
		System.out.print("all_k_neigh:");
		printKneight(all_k_neigh);
		System.out.print("all_k_neigh_sorted:");
		printKneight(all_k_neigh_sorted);
		// intersectionOfKNN(all_k_neigh,0,1);
		int[] label = new int[points.size()];
		for (int i = 0; i < points.size(); i++) {
			label[i] = -1;
		}
		System.out.println("label: " + label[0]);
		int labelnum = 0;
		List<Integer> clustercenters = new ArrayList<>();
		int[] inornotqueue = new int[points.size()];
		for (int i = 0; i < points.size(); i++) {
			inornotqueue[i] = -1;
		}
		System.out.println("inornotqueue: " + inornotqueue[0]);
		
		for (int i = 0; i < all_k_neigh_sorted.size(); i++) {
			Integer centerid = all_k_neigh_sorted.get(i).getId();
			Double centerid_minr = all_k_neigh_sorted.get(i).getMinradius();
			List<String[]> Sk_centerid = all_k_neigh_sorted.get(i).getList();
			System.out.print("centerid:" + centerid + ",");
			System.out.println("centerid_minr:" + centerid_minr);
			if (label[centerid] != -1)
				continue;
			else {
				labelnum += 1;
				label[centerid] = labelnum;
				clustercenters.add(centerid);
			}
			Comparator<Kneigh> OrderIsdn = priorityQueueSet();
			Queue<Kneigh> integerPriorityQueue = new PriorityQueue<>(OrderIsdn); // 优先队列
			integerPriorityQueue.add(new Kneigh(centerid, centerid_minr));
			inornotqueue[centerid] = 1;

			while (!integerPriorityQueue.isEmpty()) {
				System.out.println("进入while循环");
				Kneigh kneighpoll = integerPriorityQueue.poll();
				System.out.println("出列");
				Double nothing1 = kneighpoll.getMinradius();
				Integer xid = kneighpoll.getId();
				 System.out.println("xid:"+xid+","+"nothing1:"+nothing1);
				 System.out.println("剩余队列大小："+integerPriorityQueue.size());	 
				Integer xnullid = all_k_neigh.get(xid).getId();
				Double x_dk = all_k_neigh.get(xid).getMinradius();
				List<String[]> x_Sknn = all_k_neigh.get(xid).getList(); // 实际上
				 System.out.println("xnullid:"+xid+","+"x_dk:"+nothing1);
				// 计算x新的k_new近邻
				List<Kneigh> x_new_Sknn = new ArrayList<>();
				for (int ii = 0; ii < x_Sknn.size(); ii++) {
					Double d = Double.parseDouble(x_Sknn.get(ii)[0]);
					Integer id = Integer.parseInt(x_Sknn.get(ii)[1]);
					 System.out.println("id:"+id+","+"d:"+d);
					if (label[id] == labelnum || label[id] == -1) {    //如果id是本簇的，或者id没有标号
						x_new_Sknn.add(new Kneigh(id, d));
					}
				}

				for (int iii = 0; iii < x_new_Sknn.size(); iii++) { // 对于本簇的点
					 System.out.println("对于本簇的点:");
					Double dis = x_new_Sknn.get(iii).getMinradius();
					Integer yid = x_new_Sknn.get(iii).getId();
					 System.out.println("yid:"+yid+","+"dis:"+dis);
					if (label[yid] != labelnum || inornotqueue[yid] == 1) {
						continue;
					}
					Integer nulpid = all_k_neigh.get(yid).getId();
					Double y_dk = all_k_neigh.get(yid).getMinradius();
					List<String[]> y_Sknn = all_k_neigh.get(yid).getList();
					System.out.println("nulpid:"+yid+","+"y_dk:"+dis);
					List<Kneigh> y_new_Sknn = new ArrayList<>();
					 System.out.println("y_Sknn.size(): "+y_Sknn.size());
					for (int iiii = 0; iiii < y_Sknn.size(); iiii++) {
						Double d = Double.parseDouble(y_Sknn.get(iiii)[0]);
						Integer id = Integer.parseInt(y_Sknn.get(iiii)[1]);
						 System.out.println("id2:"+id+","+"d2:"+d);
						if (label[id] == labelnum | label[id] == -1) {
							y_new_Sknn.add(new Kneigh(id, d));
						}
					}
					int k1 = x_new_Sknn.size();
					int k2 = y_new_Sknn.size();
					int k3 = getMin(k1, k2);
					 System.out.println("k1="+k1+" k2="+k2+" k3="+k3);
					if (k3 == 0)
						continue;
					Double x_new_dk = x_new_Sknn.get(k3 - 1).getMinradius();
					Double y_new_dk = y_new_Sknn.get(k3 - 1).getMinradius();
					Double deltadk = Math.abs(x_new_dk - y_new_dk) / x_new_dk;
					System.out.println("x_new_dk: "+x_new_dk+" y_new_dk: "+y_new_dk+" deltadk: "+deltadk);
					if (deltadk < epsilon) {
						integerPriorityQueue.add(new Kneigh(yid, y_new_dk));
						System.out.println("入列");
						 inornotqueue[yid]=1;
					}
				}

				// 对于未标记的点
				for (int iii = 0; iii < x_new_Sknn.size(); iii++) {
					 System.out.println("对于未标记的点");
					Double dis = x_new_Sknn.get(iii).getMinradius();
					Integer yid = x_new_Sknn.get(iii).getId();
					 System.out.println("dis: "+dis+" yid: "+yid);
					if (label[yid] != -1)
						continue;
					int intersectNum = intersectionOfKNN(all_k_neigh, xid, yid);   //求交集
					if (intersectNum < intersect_rate * k) // 1.5
						continue;
					Integer nulpid = all_k_neigh.get(yid).getId();
					Double y_dk = all_k_neigh.get(yid).getMinradius();
					List<String[]> y_Sknn = all_k_neigh.get(yid).getList();
					 System.out.println("nulpid:"+nulpid+" y_dk:"+y_dk); //实际上
					List<Kneigh> y_new_Sknn = new ArrayList<>();
					for (int iiii = 0; iiii < y_Sknn.size(); iiii++) {
						Double d = Double.parseDouble(y_Sknn.get(iiii)[0]);
						Integer id = Integer.parseInt(y_Sknn.get(iiii)[1]);
						 System.out.println("id3: "+id+"d3: "+d);
						if (label[id] == labelnum || label[id] == -1) {
							y_new_Sknn.add(new Kneigh(id, d));
						}
					}
					int k1 = x_new_Sknn.size();
					int k2 = y_new_Sknn.size();
					int k3 = getMin(k1, k2);
					System.out.println("k1="+k1+" k2="+k2+" k3="+k3);
					if (k3 == 0)
						continue;
					label[yid] = labelnum;
					Double x_new_dk = x_new_Sknn.get(k3 - 1).getMinradius();
					Double y_new_dk = y_new_Sknn.get(k3 - 1).getMinradius();
					Double deltadk = Math.abs(x_new_dk - y_new_dk) / x_new_dk;
					 System.out.println("x_new_dk: "+x_new_dk+" y_new_dk: "+y_new_dk+" deltadk: "+deltadk);
					if (deltadk < epsilon) {
						integerPriorityQueue.add(new Kneigh(yid, y_new_dk));
						System.out.println("入列");
						inornotqueue[yid] = 1;
					}
				}

			} // while循环结束

		} // for循环结束

		labelnum = postProcess(all_k_neigh, all_k_neigh_sorted, clustercenters, label, points, k);

		System.out.println("labelnum = " + labelnum);
		System.out.println("clustercenters = " + clustercenters);
		for (int i = 0; i < points.size(); i++) {
			System.out.print("label = " + label[i] + ",");
		}

		Map<Integer, List<Integer>> cluster_list = new HashMap<>();
		for (int i = 0; i < points.size(); i++) {
			if (cluster_list.get(label[i]) == null) {
				List<Integer> keyValue = new ArrayList<>();
				cluster_list.put(label[i], keyValue);
			}
			cluster_list.get(label[i]).add(i);
		}

		// 打印
		System.out.println("打印分类");
		for (Map.Entry<Integer, List<Integer>> entry : cluster_list.entrySet()) {
			System.out.print(entry.getKey() + ": [");
			for (int i = 0; i < entry.getValue().size(); i++) {
				if (i == entry.getValue().size() - 1) {
					System.out.println(entry.getValue().get(i) + "]");
					continue;
				}
				System.out.print(entry.getValue().get(i) + ",");
			}
		}

		showChart(points, label, labelnum, clustercenters, cluster_list);
		
	}
	


	public static void showChart(List<String[]> points, int[] label, int labelnum, List<Integer> clustercenters,
			Map<Integer, List<Integer>> cluster_list) {
		System.out.println("开始绘图");	
		DefaultXYDataset xydataset = new DefaultXYDataset();
		Map<Integer, double[][]> map = new HashMap<>();
		double[][] clustercenters_datas = new double[2][clustercenters.size()];
		for (int j = 0; j < labelnum; j++) {
			for (int i = 0; i < clustercenters.size(); i++) {
				System.out.println("clustercenters.size()" + clustercenters.size());
				int id = clustercenters.get(i);
				System.out.print("id:" + id + ",");
				clustercenters_datas[0][i] = Double.parseDouble(points.get(id)[0]);
				clustercenters_datas[1][i] = Double.parseDouble(points.get(id)[1]);
			}
		}
		map.put(0, clustercenters_datas);
		for (Map.Entry<Integer, List<Integer>> entry : cluster_list.entrySet()) {
			double[][] points_datas = new double[2][points.size()];
			System.out.println("entry.getKey()" + entry.getKey());
			System.out.println(entry.getValue().size());
			for (int i = 0; i < entry.getValue().size(); i++) {
				// System.out.println(entry.getValue().get(i));
				int id = entry.getValue().get(i);
				System.out.print("id:" + id + ",");
				points_datas[0][i] = Double.parseDouble(points.get(id)[0]);
				points_datas[1][i] = Double.parseDouble(points.get(id)[1]);
				System.out.print("xy" + points_datas[0][i] + "," + points_datas[1][i] + ",");

			}
			System.out.println();
			System.out.println(entry.getKey());
			map.put(entry.getKey(), points_datas);
		}
		// 根据类别建立数据集
		for (Entry<Integer, double[][]> entry : map.entrySet()) {
			double[][] datas = entry.getValue();
			System.out.print(entry.getKey() + ",");
			System.out.println(datas);
			xydataset.addSeries(entry.getKey(), datas);
		}
		JFreeChart chart = ChartFactory.createScatterPlot("NIDDCluster", "X", "Y", xydataset, PlotOrientation.VERTICAL,
				true, false, false);
		ChartFrame frame = new ChartFrame("NIDDCluster", chart, true);
		chart.setBackgroundPaint(Color.white);
		chart.setBorderPaint(Color.GREEN);
		chart.setBorderStroke(new BasicStroke(1.5f));
		XYPlot xyplot = (XYPlot) chart.getPlot();

		xyplot.setBackgroundPaint(new Color(255, 253, 246));// 绘图背景
		ValueAxis vaaxis = xyplot.getDomainAxis();
		vaaxis.setAxisLineStroke(new BasicStroke(1.5f));

		ValueAxis va = xyplot.getDomainAxis(0);
		va.setAxisLineStroke(new BasicStroke(1.5f));

		va.setAxisLineStroke(new BasicStroke(1.5f)); // 坐标轴粗细
		va.setAxisLinePaint(new Color(215, 215, 215)); // 坐标轴颜色
		xyplot.setOutlineStroke(new BasicStroke(1.5f)); // 边框粗细
		va.setLabelPaint(new Color(10, 10, 10)); // 坐标轴标题颜色
		va.setTickLabelPaint(new Color(102, 102, 102)); // 坐标轴标尺值颜色
		ValueAxis axis = xyplot.getRangeAxis();
		axis.setAxisLineStroke(new BasicStroke(1.5f));

		// 设置绘制点的颜色
		XYLineAndShapeRenderer xylineandshaperenderer = (XYLineAndShapeRenderer) xyplot.getRenderer();
		xylineandshaperenderer.setSeriesOutlinePaint(0, Color.black);
		// xylineandshaperenderer.setSeriesPaint(0, Color.green);
		xylineandshaperenderer.setUseOutlinePaint(true);

		NumberAxis numberaxis = (NumberAxis) xyplot.getDomainAxis();
		numberaxis.setAutoRangeIncludesZero(false);
		numberaxis.setTickMarkInsideLength(2.0F);
		numberaxis.setTickMarkOutsideLength(0.0F);
		numberaxis.setAxisLineStroke(new BasicStroke(1.5f));

		frame.pack();
		frame.setVisible(true);
	}

	// 后处理
	public static int postProcess(List<Kneigh> all_k_neigh, List<Kneigh> all_k_neigh_sorted,
			List<Integer> clustercenters, int[] label, List<String[]> points, int k) {
		Map<Integer, List<Integer>> cluster_list = new HashMap<>();
		for (int i = 0; i < points.size(); i++) {
			if (cluster_list.get(label[i]) == null) {
				List<Integer> keyValue = new ArrayList<>();
				cluster_list.put(label[i], keyValue);
			}
			cluster_list.get(label[i]).add(i);
		}

		// 打印
		System.out.println("后处理打印");
		for (Map.Entry<Integer, List<Integer>> entry : cluster_list.entrySet()) {
			System.out.print(entry.getKey() + ": [");
			for (int i = 0; i < entry.getValue().size(); i++) {
				if (i == entry.getValue().size() - 1) {
					System.out.println(entry.getValue().get(i) + "]");
					continue;
				}
				System.out.print(entry.getValue().get(i) + ",");
			}
		}

		// 如果簇太小，则合并
		List<Integer> del_list = new ArrayList<>();
		for (Map.Entry<Integer, List<Integer>> entry : cluster_list.entrySet()) {
			System.out.println(entry.getValue());
			System.out.println("循环开始");
			if (entry.getValue().size() < k) { // 则认为他不是一个簇，需要合并，看它们的k近邻大多属于哪个簇，它就属于哪个簇
				System.out.println("entry.getKey():"+entry.getKey());
				Map<Integer, Integer> count_dict = new HashMap<>();
				for (Integer jj = 0; jj < entry.getValue().size(); jj++) { // cluster_i表示一个小簇,点的集合。是一个列表
					Integer j = entry.getValue().get(jj);
					System.out.println("J::"+j);
					List<String[]> Sk = all_k_neigh.get(j).getList();
						for(int aa=0;aa<Sk.size();aa++){
						int dist_id=Integer.parseInt(Sk.get(aa)[1]);
						if (!entry.getValue().contains(dist_id)) { // id是j点的k近邻中的点，如果它不在簇i中，则。。。。							
							if (count_dict.get(label[dist_id]) == null) {
								count_dict.put(label[dist_id], 0);
								System.out.println("label[Integer.parseInt(dist_id[1])]:"+label[dist_id]);
							}
							Integer i = count_dict.get(label[dist_id])+1;
							count_dict.put(label[dist_id], i);
							System.out.println("label[Integer.parseInt(dist_id[1])]:"+label[dist_id]+" i::"+i);
						}
					}					
					if (count_dict.size() != 0) {
						Integer cnum = 0, cnumValue = 0;
						for (Map.Entry<Integer, Integer> i : count_dict.entrySet()) {
							if (i.getValue() > cnumValue) {
								cnum = i.getKey();
								cnumValue = i.getValue();
							}
						}
						label[j] = cnum;
						cluster_list.get(cnum).add(j);
					}
				}
				del_list.add(entry.getKey());
			}
		}//集合循环结束
		System.out.println("循环结束");
		for (Integer ii = 0; ii < del_list.size(); ii++) {
			Integer j = del_list.get(ii);
			cluster_list.remove(j);
		}

		return adjustClusters(label, clustercenters);

	}

	public static int adjustClusters(int[] label, List<Integer> clustercenters) {
		// 有些簇合并了，需要调整簇标号
		Set<Integer> all_labels_set = new HashSet<>();	
		for (int i : label) {
			all_labels_set.add(i);
		}
		int c = 0;
		Map<Integer, Integer> dict = new HashMap<>();
		for (Integer s : all_labels_set) {
			c += 1;
			dict.put(s, c);
		}
		for (int i = 0; i < label.length; i++) { // 其实就是做一个映射。因为标签可能不连续，
			int key = label[i];
			int newvalue = dict.get(key);
			label[i] = newvalue;
		}
		// 调整簇中心
		dict.clear();
		for (int i = 0; i < clustercenters.size(); i++) {
			int id = clustercenters.get(i);
			Integer key = label[id];
			Integer value = id;
			if (dict.get(key) == null) {
				dict.put(key, value);
			}
		}
		clustercenters.clear();
		for (Map.Entry<Integer, Integer> entry : dict.entrySet()) {
			clustercenters.add(entry.getValue());
		}

		return all_labels_set.size();
	}

	public static int getMin(int a, int b) {

		if (a > b)
			return b;
		else if (a < b)
			return a;
		else
			return b;
	}

	// 打印对象
	public static void printKneight(List<Kneigh> k_neigh) {
		System.out.println();
		for (int i = 0; i < k_neigh.size(); i++) {
			System.out.print("(" + k_neigh.get(i).getId() + ",");
			System.out.print(k_neigh.get(i).getMinradius() + "), ");
			for (String[] value : k_neigh.get(i).getList()) {

				System.out.print("(" + value[0] + ",");
				System.out.print(value[1] + ")");
			}
			System.out.println("");

		}
	}

	// 取交集，返回个数
	public static int intersectionOfKNN(List<Kneigh> k_neigh, int pid1, int pid2) {

		Set<String> neigh_id1_list = new HashSet<String>();
		Set<String> neigh_id2_list = new HashSet<String>();
		Set<String> result = new HashSet<String>();
		for (int i = 0; i < k_neigh.get(pid1).getList().size(); i++) {
			neigh_id1_list.add(k_neigh.get(pid1).getList().get(i)[1]);
		}
		for (int i = 0; i < k_neigh.get(pid2).getList().size(); i++) {
			neigh_id2_list.add(k_neigh.get(pid2).getList().get(i)[1]);
		}
		result.clear();
		result.addAll(neigh_id1_list);
		result.retainAll(neigh_id2_list);
		System.out.println("交集：" + result);
		System.out.println("交集个数：" + result.size());

		return result.size();
	}

	// 构造排序方式(优先队列的最小半径优先出列)
	public static Comparator<Kneigh> priorityQueueSet() {

		Comparator<Kneigh> OrderIsdn = new Comparator<Kneigh>() {
			public int compare(Kneigh o1, Kneigh o2) {
				// TODO Auto-generated method stub
				Double numbera = o1.getMinradius();
				Double numberb = o2.getMinradius();
				if (numberb < numbera) {
					return 1;
				} else if (numberb > numbera) {
					return -1;
				} else {
					return 0;
				}
			}
		};
		return OrderIsdn;
	}

	// 按照升序进行最小半径排序
	public static List<Kneigh> sortKneight(List<Kneigh> k_neigh) {

		Collections.sort(k_neigh, new Comparator<Kneigh>() {
			@Override
			public int compare(Kneigh o1, Kneigh o2) {
				if (o1.getMinradius() > o2.getMinradius()) {
					return 1;
				}
				else if(o1.getMinradius() < o2.getMinradius())
				return -1;
				else return 0;
			}
		});
		return k_neigh;
	}

	// 返回两点间距离
	public static Double getDistance(String[] p1, String[] p2) {
		Double[] d1 = DataTypeConversion.StringArrayToDouble(p1);
		Double[] d2 = DataTypeConversion.StringArrayToDouble(p2);
		double distance = 0.0;
		for (int i = 0; i < d1.length; i++) {
			for (int j = i; j < d2.length;) {
				distance += Math.pow((d1[i] - d2[j]), 2);
				break;
			}
		}
		return Math.pow(distance, 0.5);
	}

	// 返回距离矩阵
	public static double[][] getDistanceMatrix(List<String[]> points) {

		int n = points.size();
		double[][] distanceMatrix = new double[n][n];
		String[] p1;
		String[] p2;
		double d = 0.0;
		for (int k = 0; k < points.size(); k++) {
			for (int l = k + 1; l < points.size(); l++) {
				p1 = new String[points.get(k).length];
				p2 = new String[points.get(k).length];
				p1 = points.get(k);
				p2 = points.get(l);
				d = getDistance(p1, p2);
				distanceMatrix[k][l] = d;
			}
		}

		System.out.println("内部方法打印--->>距离矩阵：");
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				System.out.print(distanceMatrix[i][j] + ", ");
			}
			System.out.println();
		}
		return distanceMatrix;
	}

	// 返回k个最近邻
	public static List<Kneigh> findTopKNeighbors(List<String[]> points, double[][] distanceMatrix, int k) {
		List<Kneigh> k_neigh = new ArrayList<>();
		System.out.println(points.size());
		for (int i = 0; i < points.size(); i++) {
			List<String[]> neigh_list = new ArrayList<>();
			Kneigh kneigh = new Kneigh();
			for (int j = 0; j < points.size(); j++) {
				if (i < j) {
					neigh_list.add(new String[] { Double.toString(distanceMatrix[i][j]), Integer.toString(j) });
				} else
					neigh_list.add(new String[] { Double.toString(distanceMatrix[j][i]), Integer.toString(j) });
			}
			sortList(neigh_list);
			List<String[]> kneigh_list = neigh_list.subList(1, k + 1);
			String[] maxKneigh = new String[2];
			maxKneigh = kneigh_list.get(k - 1);
			maxKneigh[1] = Integer.toString(i);
			double dmaxKneigh = Double.parseDouble(maxKneigh[0]);
			kneigh.setId(i);
			kneigh.setMinradius(dmaxKneigh);
			kneigh.setList(kneigh_list);
			k_neigh.add(kneigh);
		}
		return k_neigh;
	}

	// list排序
	public static void sortList(List<String[]> neigh_list) {
		Collections.sort(neigh_list, new Comparator<Object[]>() {
			@Override
			public int compare(Object[] o1, Object[] o2) {
				if (Double.valueOf(o1[0].toString()) > Double.valueOf(o2[0].toString())) {
					return 1;
				}
				else if(Double.valueOf(o1[0].toString()) < Double.valueOf(o2[0].toString()))
				return -1;
				else return 0;
			}
		});
	}

	// 返回map排序，主键是数组(取出最小半径进行排序)
	public static Map<String[], List<String[]>> sortMapByKey(Map<String[], List<String[]>> oriMap) {
		if (oriMap == null || oriMap.isEmpty()) {
			return null;
		}
		Map<String[], List<String[]>> sortedMap = new TreeMap<String[], List<String[]>>(new Comparator<String[]>() {
			@Override
			public int compare(String[] o1, String[] o2) {
				if (Double.valueOf(o1[0].toString()) > Double.valueOf(o2[0].toString())) {
					return 1;
				}
				return -1;
			}
		});
		sortedMap.putAll(oriMap);
		return sortedMap;
	}

	// 打印k近邻排序后的结果
	public static void printAll_k_neigh(Map<String[], List<String[]>> all_k_neigh) {
		for (Map.Entry entry : all_k_neigh.entrySet()) {
			String[] key = (String[]) entry.getKey();
			List<String[]> list = (List<String[]>) entry.getValue();
			System.out.print(key[1] + " ,");
			System.out.print(key[0] + ", ");
			for (int i1 = 0; i1 < list.size(); i1++) {
				for (int j = 0; j < list.get(i1).length; j++) {
					System.out.print(list.get(i1)[j] + ", ");
				}
			}
			System.out.println();
		}
	}

}

